perm filename GRNSAI.SAI[S,HE] blob
sn#811590 filedate 1983-09-16 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00027 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00004 00002 These routines are for outputting gray-level pictures on the Grinnell.
C00010 00003 INTERNAL PROCEDURE SNOOZE(INTEGER TIME(0))
C00013 00004 PROCEDURE PUPERROR(INTEGER ErrorCode String ErrMess)
C00015 00005 PROCEDURE START11
C00016 00006 PROCEDURE ENETSTART
C00019 00007 PROCEDURE ENETOUT(INTEGER ARRAY INSTRUCTIONS INTEGER INSTLEFT)
C00021 00008 INTERNAL PROCEDURE BUFOUT
C00025 00009 INTERNAL INTEGER PROCEDURE ENETWORDIN
C00026 00010 INTERNAL INTEGER PROCEDURE GWORDIN
C00028 00011 INTERNAL PROCEDURE GRNINI
C00033 00012 INTERNAL SIMPLE PROCEDURE DEMOMODE(STRING DEVICE,FILENAME)
C00035 00013 INTERNAL PROCEDURE GRNFIN
C00036 00014 PROCEDURE DEMOWORD(INTEGER WORD)
C00037 00015 INTERNAL SIMPLE PROCEDURE GRNINS(INTEGER WORD)
C00039 00016 INTERNAL PROCEDURE ENETIN(INTEGER ARRAY_ADDR, WORDCOUNT, READBACKMODE(0))
C00041 00017 INTERNAL PROCEDURE GRNIN(INTEGER ADDR, COUNT, READBACKMODE(0), USETBITS(0))
C00046 00018 INTERNAL SIMPLE PROCEDURE EXE11BUF(INTEGER ADDR, BUFLEN)
C00052 00019 INTERNAL PROCEDURE TSTGRN(INTEGER TESTNO)
C00053 00020 INTERNAL PROCEDURE MAPGRN(INTEGER CARD,TABL,NBITS)
C00054 00021 INTERNAL PROCEDURE ERASEG(INTEGER CHAN,BITS('7777))
C00055 00022 INTERNAL PROCEDURE VIDGRN(INTEGER LEFT, TOP, CHAN INTEGER ARRAY PIC
C00060 00023 PROCEDURE PACKBYTES(INTEGER BYTE1PTR, BYTE2PTR,DESTPTR, NBYTES)
C00061 00024 INTERNAL PROCEDURE InLine(REFERENCE INTEGER Ptr INTEGER linelen)
C00062 00025 INTERNAL PROCEDURE INPIC(INTEGER CHAN INTEGER ARRAY PIC)
C00064 00026 INTERNAL PROCEDURE UINPIC(INTEGER CHAN INTEGER ARRAY PIC)
C00067 00027 END "GRNSAI"
C00068 ENDMK
C⊗;
Comment These routines are for outputting gray-level pictures on the Grinnell.
They are a temporary hack to "hold the dike" until the device-independent
graphics library can be completed and should be regarded as such. AAM '80;
Comment Hah! Such youthful optimism. AAM '82;
Comment Temporary my ass. Added Ethernet bullshit. AAM,CR '83;
ENTRY VIDGRN,TSTGRN,MAPGRN,GRNINI,GRNFIN,GRNINS,BUFOUT, SNOOZE, GRNIN, GWORDIN,
ENETWORDIN,INPIC, ENETIN,
EXE11BUF, QUICKGIN, QUICKBUF;
BEGIN "GRNSAI"
Comment misc. definitions;
REQUIRE "{}<>" DELIMITERS;
REQUIRE "GRNFHD.SAI[HDR,HE]" SOURCE_FILE;
REQUIRE "PIXHDR.SAI[HDR,HE]" SOURCE_FILE;
REQUIRE "GRNDEF[HDR,HE]" SOURCE_FILE;
REQUIRE "ELFHDR.SAI[HDR,HE]" SOURCE_FILE;
REQUIRE "CRDHDR.SAI[HDR,HE]" SOURCE_FILE;
REQUIRE "PUPFAI[S,HE]" LOAD_MODULE;
REQUIRE "PUPFAI.ENV[HDR,HE]" SOURCE_FILE;
REQUIRE "PUPSAI[S,HE]" LOAD_MODULE;
REQUIRE "PUPSAI.ENV[HDR,HE]" SOURCE_FILE;
DEFINE TRACE={FALSE}; COMMENT Print out debugging marks;
comment DEFINE TRACE={TRUE}; COMMENT Print out debugging marks;
DEFINE SEEINSTR={FALSE}; COMMENT Look at Grinnell instructions in octal before executring them;
DEFINE HANGNOISY={TRUE}; COMMENT Complain loudly when DR11 hangs;
DEFINE HANGWAIT={FALSE}; COMMENT Allow user to examine signals before resetting
PDP11 when DR11 hangs;
DEFINE HANGRETRY={FALSE}; COMMENT When DR11 hangs, keep retrying until it doesn't;
DEFINE SPEEDCHECK={FALSE}; COMMENT Special timing hacks;
DEFINE GRNDEV={TRUE}; COMMENT Grinnell a device yet?;
DEFINE BUSTCHK={FALSE}; COMMENT Check BUSTED.GRN for latest status?;
DEFINE VAXCHK={TRUE}; COMMENT Check ONVAX.GRN to see if Grinnell is on the vax;
DEFINE ! = {COMMENT};
DEFINE CRLF = { ('15&'12) };
DEFINE GRNBUF(BUFFER,BUFLEN,BITS) = {
Comment Cause DR-11B to do its thing;
IF NOT BUSTED THEN
BEGIN
WAITFOR11;
IFC TRACE THENC print("!"); ENDC
ELFBKO(START11MEM,(BUFLEN),BUFFER,(BITS)); Comment move the buffer to the 11;
ELFOUT(DRWC,-(BUFLEN)); Comment NOTE: word count not byte count;
ELFOUT(DRBA,(START11MEM LAND '177777) LSH 1); comment MAKE INTO BYTE ADR;
ELFOUT(DRST,DRWRITE); comment Grinnell needs at least one clock;
ELFOUT(DRST,GO LOR DRWRITE LOR XBA); comment cycle between setting of;
comment write and go;
END;
}; ! end of GRNBUF;
Comment global variables;
BOOLEAN DEMO; COMMENT Whether a demo file is being created;
INTEGER DEMOCHAN; COMMENT The channel the file is open on;
INTEGER DEMOSAVE; COMMENT Word used to pack instructions;
BOOLEAN EVENWORD;
INTEGER DEMBREAK,DEMEOF; COMMENT For demo file stuff;
BOOLEAN BUSTED; Comment Whether or not Grinnell is in normal mode;
INTEGER NXTLOC; Comment next PDP11 address to load;
SAFE Comment to speed up GRNINS;
INTEGER ARRAY INSBUF[1:LEN11MEM]; Comment 10-buffer for 11 memory.;
INTEGER BUFSIZE; Comment No. of 16-bit words that go in INSBUF;
INTEGER LOKCHAN; Comment channel used for opening file which locks grinnell;
BOOLEAN ONVAX; ! Set to true if the grinnell is on the Whitney;
INTEGER PUPCHAN; ! Channel for ethernet communication to Whitney;
INTEGER PUP36SIZE,PUP16SIZE; ! Size of PUP buffer in system;
BOOLEAN CONNECTED; ! Set to true if a connection has been established;
INTERNAL PROCEDURE SNOOZE(INTEGER TIME(0));
Comment SNOOZE is the delay that is used for waiting for the DR11-B;
Comment sleeps for 1/60 of a second (until next tick, I guess);
Comment unless argument is nonzero, then it sleeps that many seconds;
BEGIN "SNOOZE"
QUICK_CODE "SLEEP"
MOVE '13,TIME;
CALLI '13,'31
END "SLEEP";
IFC TRACE THENC Print(":"); ENDC
END "SNOOZE"; Comment what a kludge;
INTERNAL PROCEDURE WAITFOR11;
BEGIN "WAITFOR11"
INTEGER SLEEPY;
Comment wait until the DR11B is ready and the arm is not moving;
SLEEPY ← 0;
WHILE ¬(ELFIN(DRST) LAND READY) DO
BEGIN SNOOZE; SLEEPY ← SLEEPY+1;
IFC TRACE THENC
! IF SLEEPY > 20 THEN ;
PRINT("DRST: ",CVOS(ELFIN(DRST)),'15&'12);
ENDC
COMMENT Added code to check for hanging not due to Grinnell;
IF SLEEPY > 120 COMMENT Allow 2 sec for this one;
THEN BEGIN "HUNG BUT NOT OUR FAULT"
STRING RESET;
PRINT("The PDP-11 appears to be hung. Shall I try a RESET?");
PRINT('15&'12&"Don't say yes unless you are prepared to deal with");
PRINT('15&'12&"an angry arm hacker (check first): ");
RESET←INCHWL;
IF (RESET="Y") OR (RESET="y") THEN POWERFAIL ELSE
BEGIN "HARLYNS HACK"
COMMENT This works sometimes;
PRINT("Trying recovery by zeroing wordcount."&'15&'12);
ELFOUT(DRWC,0);
ELFOUT(DRST,0);
END "HARLYNS HACK";
SLEEPY←0;
END "HUNG BUT NOT OUR FAULT";
END;
END "WAITFOR11";
PROCEDURE PUPERROR(INTEGER ErrorCode; String ErrMess);
Comment This routine checks outputs a message according to the error code;
BEGIN "PUPERROR"
IF ErrorCode ≠ 0
Then Begin
Print(ErrMess,crlf);
Case ErrorCode OF Begin
[1] Print("Illegal channel number");
[2] Print("OPEN failed on device PUP");
[3] Print("MTAPE to establish connection failed");
[4] Print("OUT failed while outputting buffer");
[5] Print("IN failed while reading buffer");
[6] Print("odd number of bytes in packet on input");
[7] Print("block-mode output buffer too long");
ELSE Print("Unknown Error: ",ErrorCode)
End;
Print(crlf);
End;
END "PUPERROR";
PROCEDURE START11;
Comment This routine initializes the connection for the Grinnell to the
PDP-11.;
BEGIN "START11"
ELFINI;
BUFSIZE←LEN11MEM; Comment one pdp-11 word per Grn instruction;
END;
PROCEDURE ENETSTART;
Comment This routine initializes an ethernet connection to the VAX for
sending instructions to the grinnell.
Sets CONNECTED to True if a connection is established.
Initializes PUP36SIZE to the number of 36-bit words that can be sent
in one block;
BEGIN "ENETSTART"
INTEGER ErrorCode,
ConStatus;
STRING ERRMESS;
BOOLEAN FOUND;
INTEGER ARRAY HOSTSOCKET[0:5];
PupChan ← 6; ! This must be changed *****;
Connected ← False;
IFC TRACE THENC
Print("Looking up grinnell on whitney: ",crlf);
ENDC
NAMELOOKUP("whitney+grinnell-server",HOSTSOCKET,FOUND,ERRMESS);
If NOT FOUND then
Print("Error connecting to whitney: ",ERRMESS,crlf)
Else
BEGIN
IFC TRACE THENC
Print("Initing connection",crlf);
ENDC
ErrorCode ← PupInit(PupChan,HOSTSOCKET[1],HOSTSOCKET[5],BUFSIZE);
BUFSIZE ← BUFSIZE - 2; comment leave room for header;
If ErrorCode ≠ 0 Then
PupError(ErrorCode,
"Error Initializing Connection - No graphics will be done")
Else
Begin ! Get handshake;
ErrorCode ← PupIn(ConStatus);
If (ErrorCode = 0) and (ConStatus = 0) Then
Begin
Connected ← True;
IFC TRACE THENC
print("Successful open. buffer size: ",bufsize,crlf);
ENDC
End
Else If (ErrorCode ≠ 0) Then Begin
PupError(ErrorCode,
"Could not input handshake - No graphics will be done");
PupFini;
End
Else If (ConStatus ≠ 0) Then Begin
Print("Could not open Grinnel on Vax",crlf);
Pupfini;
End;
End;
END;
PUP36SIZE ← BUFSIZE DIV 2; ! Buffer Len in 36 bit words;
END "ENETSTART";
PROCEDURE ENETOUT(INTEGER ARRAY INSTRUCTIONS; INTEGER INSTLEFT);
BEGIN "ENETOUT"
Comment This routine outputs an instruction buffer to the currently opened
Ethernet connection.;
INTEGER ERR, ! Error code retruned from pup routines;
LENPACKET, ! Length of packet to be sent;
ENDPACKET, ! Array loc of last instruction for current packet;
INSTCOUNTER;
IF CONNECTED THEN BEGIN
INSTCOUNTER ← ARRINFO(INSTRUCTIONS, 1); ! Gets lower bound of array;
! Output instuction buffer until no more instructions are left;
ERR ← 0;
WHILE (INSTLEFT > 0) AND (ERR = 0) DO BEGIN
PUPOUT(GRNWRITE); ! Send write indicator;
LENPACKET ← (BUFSIZE - 2) MIN INSTLEFT;
PUPOUT(LENPACKET); ! Send length;
INSTLEFT ← INSTLEFT - LENPACKET;
ENDPACKET ← INSTCOUNTER + LENPACKET - 1;
WHILE (INSTCOUNTER ≤ ENDPACKET) AND (ERR = 0) DO BEGIN
ERR ← PUPOUT(INSTRUCTIONS[INSTCOUNTER]);
INSTCOUNTER ← INSTCOUNTER + 1;
END;
IF ERR = 0 THEN ERR ← PUPFLUSH;
END;
PUPERROR(ERR, "Error while outputting instruction buffer");
END;
END "ENETOUT";
INTERNAL PROCEDURE BUFOUT;
Comment BUFOUT outputs any pending Grinnell commands from the 10 memory to the
Grinnell.;
BEGIN "BUFOUT"
INTEGER BUFLEN,SLEEPY; Comment number of words to output, No. of sleep cycles;
BUFLEN ← NXTLOC - 1; Comment because NXTLOC points to the NEXT location.;
IF BUFLEN > 0 THEN
BEGIN
IF ONVAX THEN
ENETOUT(INSBUF,BUFLEN)
ELSE
GRNBUF(INSBUF,BUFLEN,0);
NXTLOC ← 1 comment restart word count;
END
END "BUFOUT";
INTERNAL INTEGER PROCEDURE ENETWORDIN;
BEGIN "ENETWORDIN"
Comment This routine inputs data from the grinnell over the ethernet connection.;
INTEGER Word;
IF CONNECTED THEN BEGIN
BUFOUT;
PUPERROR(PUPIN(WORD),"Error while inputing grinnell data");
RETURN(WORD);
END;
END "ENETWORDIN";
INTERNAL INTEGER PROCEDURE GWORDIN;
BEGIN "GWORDIN"
Comment This procedure causes the 11 to read a word from the
Grinnell interface and then returns this value. It should be uesd after
a read back instruction is given;
IF NOT BUSTED THEN
BEGIN
IF ONVAX THEN RETURN(ENETWORDIN)
ELSE BEGIN "ELF INPUT"
BUFOUT;
Comment wait until the DR11B is ready and the arm is not moving;
WAITFOR11;
ELFOUT(DRWC, -1); ! Readback count 16 bit wds;
ELFOUT(DRBA,(START11MEM LAND '177776) LSH 1); ! MAKE INTO BYTE ADR;
ELFOUT(DRST, DRREAD);
ELFOUT(DRST, GO LOR DRREAD LOR XBA);
WAITFOR11;
RETURN(ELFIN(START11MEM))
END "ELF INPUT"
END
END "GWORDIN"; Comment input data from 11;
INTERNAL PROCEDURE GRNINI;
Comment GRNINI sets up the Grinnell buffer(set of instructions in PDP11 memory).
It should be called before GRNINS is ever called.;
BEGIN "GRNINI"
REQUIRE "APPEND[TST,AAM]" LOAD_MODULE;
EXTERNAL INTEGER PROCEDURE APPEND(INTEGER CHAN; REFERENCE INTEGER COUNT);
INTEGER COUNT,BRCHAR,EOF,FAILURE,BUSTCHAN,ACCTCHAN,SAVEW,SAVED;
STRING MINUTES;
BOOLEAN NEWFILE;
INTEGER DATE,DAY,MONTH,TICKS,MIN,HR;
ONVAX ← FALSE;
IFC VAXCHK THENC
PUPCHAN←GETCHAN;
OPEN(PUPCHAN,"SYS",0,0,0,1,BRCHAR,EOF);
Comment If SYS:ONVAX.GRN exists then the Grinnell is on the VAX;
LOOKUP(PUPCHAN,"ONVAX.GRN",FAILURE);
ONVAX ← FAILURE = 0;
RELEASE(PUPCHAN);
IFC TRACE THENC
if onvax then print("Grinnell instructions will be sent to the vax",crlf);
ENDC
ENDC
DEMO ← FALSE; COMMENT No demos unless specifically requested;
NXTLOC ← 1; Comment set up place to put instructions in buffer;
EOF ← -1;
IFC GRNDEV THENC
DO OPEN(LOKCHAN ← GETCHAN,"GRN", 0, 0,0,1,BRCHAR,EOF) UNTIL EOF = 0;
ELSEC
OPEN(LOKCHAN ← GETCHAN,"SYS", '17, 0,0,1,BRCHAR,EOF);
ENTER(LOKCHAN,"GRNLOK.TBL",FAILURE);
IF FAILURE LAND 3 THEN BEGIN comment if file is being used then wait;
PRINT("Waiting for Grinnell....");
WHILE FAILURE LAND 3 DO BEGIN
SNOOZE;
ENTER(LOKCHAN,"GRNLOK.TBL",FAILURE);
END;
PRINT("Gotcha!"&'15&'12);
END;
ENDC
IFC BUSTCHK THENC
BUSTCHAN←GETCHAN;
OPEN(BUSTCHAN,"DSK",0,0,0,1,BRCHAR,EOF);
LOOKUP(BUSTCHAN,"BUSTED.GRN[TMP,AAM]",FAILURE);
BUSTED ← FAILURE = 0;
RELEASE(BUSTCHAN);
IF BUSTED THEN PRINT("Grinnell is busted. No graphics will be done.",CRLF);
ENDC
IF ONVAX THEN ENETSTART
ELSE START11;
ACCTCHAN←GETCHAN;
OPEN(ACCTCHAN,"DSK",0,1,1,COUNT,BRCHAR,EOF);
LOOKUP(ACCTCHAN,"GRINEL.SUX[DOC,HE]",NEWFILE);
ENTER(ACCTCHAN,"GRINEL.SUX[DOC,HE]",EOF);
IF NOT NEWFILE THEN APPEND(ACCTCHAN,COUNT);
COMMENT Fix the spazz where the caller has done a SETFORMAT;
GETFORMAT(SAVEW,SAVED); SETFORMAT(0,0);
OUT(ACCTCHAN,CVXSTR(CALL(0,"GETPPN"))&'11); comment PPN;
OUT(ACCTCHAN,CVXSTR(CALL(0,"GETNAM"))&'11); comment jobname;
DATE ← CALL(0,"DATE"); DAY←(DATE MOD 31)+1; MONTH←((DATE DIV 31) MOD 12)+1;
OUT(ACCTCHAN,CVS(MONTH)&"/"&CVS(DAY)&'11);
TICKS ← CALL(0,"TIMER"); MIN←(TICKS DIV 3600)MOD 60; HR←TICKS DIV 216000;
COMMENT Make life easier for accounting programs;
MINUTES←CVS(MIN); IF LENGTH(MINUTES)<2 THEN MINUTES←"0"&MINUTES;
OUT(ACCTCHAN,CVS(HR)&":"&MINUTES&'15&'12);
SETFORMAT(SAVEW,SAVED);
RELEASE(ACCTCHAN);
END "GRNINI";
INTERNAL SIMPLE PROCEDURE DEMOMODE(STRING DEVICE,FILENAME);
COMMENT Set up demonstration mode. Call after calling GRNINI;
BEGIN "DEMOMODE"
DEMO ← TRUE;
EVENWORD ← FALSE;
DEMOCHAN ← GETCHAN;
OPEN(DEMOCHAN,DEVICE,'10,0,19,1,DEMBREAK,DEMEOF);
ENTER(DEMOCHAN,FILENAME,DEMEOF);
END "DEMOMODE";
INTERNAL PROCEDURE DEMOFIN;
COMMENT Finish off the demo file, if one exists.;
BEGIN "DEMOFIN"
IF DEMO THEN
BEGIN
COMMENT If not an even number of words, stick in a no-op at the end;
IF EVENWORD THEN WORDOUT(DEMOCHAN,(DEMOSAVE LSH 18) LOR NOP);
RELEASE(DEMOCHAN);
DEMO ← FALSE;
END;
END "DEMOFIN";
INTERNAL PROCEDURE GRNFIN;
Comment GRNFIN flushes the current Grinnell buffer and releases the ELF.;
BEGIN "GRNFIN"
BUFOUT;
DEMOFIN;
IF ONVAX THEN
BEGIN
IF CONNECTED THEN
BEGIN
PUPERROR(PupFini,"Error while closing connection.");
RELEASE(PupChan);
CONNECTED ← FALSE;
END;
END
ELSE
ELFREL;
RELEASE(LOKCHAN); Comment release file which locks grinnell;
END "GRNFIN";
PROCEDURE DEMOWORD(INTEGER WORD);
BEGIN
IF EVENWORD THEN
WORDOUT(DEMOCHAN,(DEMOSAVE LSH 18) LOR WORD)
ELSE
DEMOSAVE ← WORD;
EVENWORD ← NOT EVENWORD
END;
INTERNAL SIMPLE PROCEDURE GRNINS(INTEGER WORD);
Comment GRNINS puts our one Grinnell instruction.;
BEGIN "GRNINS"
COMMENT If we are tracing, print the instruction out.;
IFC SEEINSTR THENC
PRINT(CVOS(WORD),CRLF);
ENDC
COMMENT If we are writing a demo file, write the instruction out.;
IF DEMO THEN DEMOWORD(WORD);
INSBUF[NXTLOC] ← WORD;
NXTLOC ← NXTLOC + 1;
IF NXTLOC > BUFSIZE THEN BUFOUT
END "GRNINS";
INTERNAL PROCEDURE ENETIN(INTEGER ARRAY_ADDR, WORDCOUNT, READBACKMODE(0));
BEGIN "ENETIN"
Comment This routine inputs data from the grinnell over the ethernet connection.;
INTEGER WdCounter, Word;
IF CONNECTED THEN BEGIN
GRNINS(RPD LOR READBACKMODE);
BUFOUT;
pupout(GRNREAD); pupout(wordcount); pupflush;
IFC TRACE THENC
print("reading ",wordcount," ");
ENDC
FOR WdCounter ← 0 step 1 until WordCount - 1 DO BEGIN
PUPERROR(PUPIN(WORD),"Error while inputing grinnell data");
IFC TRACE THENC
print(WORD," ");
ENDC
MEMORY[ARRAY_ADDR + WDcounter,INTEGER] ← WORD;
END;
END;
END "ENETIN";
INTERNAL PROCEDURE GRNIN(INTEGER ADDR, COUNT, READBACKMODE(0), USETBITS(0));
BEGIN "GRNIN"
INTEGER SLEEPY,CT;
IFC HANGRETRY THENC
BOOLEAN HUNG; COMMENT Tells whether the DR11 is well hung;
ENDC
Comment This procedure causes the 11 to read count words from the
Grinnell interface and then returns this value. It should be used after
a SPD instruction with at least the readback bit set;
IF ONVAX THEN ENETIN(ADDR, COUNT, READBACKMODE)
ELSE BEGIN "ELF INPUT"
IFC HANGRETRY THENC
DO BEGIN "TRY TO READ BUFFER"
HUNG ← FALSE;
ENDC
GRNINS(RPD LOR READBACKMODE);
BUFOUT;
IF NOT BUSTED THEN
BEGIN "READ IN A BLOCK FROM GRINNELL"
WAITFOR11;
ELFOUT(DRWC, -COUNT); Comment Readback count 16 bit wds;
ELFOUT(DRBA,(START11MEM LAND '177777) LSH 1); comment MAKE INTO BYTE ADR;
ifc trace thenc
print("type <cr> to initiate read (set GO bit):");inchwl;
endc
ELFOUT(DRST, DRREAD);
ELFOUT(DRST, GO LOR DRREAD LOR XBA);
Comment Now we need to wait for the DR-11 to get finished. We used to call SNOOZE
but it always waits 1/60th sec min, which was too slow. We have experi-
mentally determined that COUNT*4 is not enough and COUNT*5 is the minimum
that works.;
CT ← COUNT*5;
QUICK_CODE
LABEL LOOP;
MOVE '13,CT;
LOOP: SOJG '13,LOOP;
END;
ifc trace thenc print("x"); endc
SLEEPY ← 0;
WHILE ¬(ELFIN(DRST) LAND READY) DO
BEGIN SNOOZE; SLEEPY←SLEEPY+1;
IFC TRACE THENC
! IF SLEEPY > 20 THEN ;
PRINT("DRST: ",CVOS(ELFIN(DRST)),'15&'12);
ENDC
comment Code has been added to detect a hung DR11B...AAM 11/4/80;
IF SLEEPY > 30 COMMENT If DR11 doesn't respond in .5 sec;
THEN BEGIN "HUNG DR11"
INTEGER I,WC;
IFC HANGNOISY THENC
Comment extend the sign of a 16-bit word (bug fixed 12/19/80 AAM);
WC←ELFIN(DRWC) LOR '777777600000;
PRINT("DR11 status register (octal) = ",CVOS(ELFIN(DRST)),CRLF);
PRINT(CRLF,"The DR-11B hung thinking it had to read ",
-WC," (decimal) more words. The words it read are:",
" (octal)",CRLF);
ELFBKI(START11MEM,COUNT+WC,ADDR,0);
FOR I←0 STEP 1 UNTIL COUNT+WC-1 DO
PRINT(CVOS(MEMORY[ADDR+I]),CRLF);
ENDC
IFC HANGWAIT THENC
PRINT("Type <cr> to do a power fail reset: ");INCHWL;
ENDC
IFC HANGRETRY THENC
HUNG ← TRUE;
ENDC
POWERFAIL;
END "HUNG DR11"
END;
IFC SPEEDCHECK THENC PRINT("I slept ",SLEEPY," times.",CRLF); ENDC
IFC HANGRETRY THENC
END "TRY TO READ BUFFER" UNTIL NOT HUNG;
ENDC
Comment check to see if words are packed when reading from the elf;
IF (USETBITS LAND TWOWRDSL) THEN COUNT ← COUNT/2 + (COUNT MOD 2);
ELFBKI(START11MEM,COUNT, ADDR,USETBITS); Comment input data from 11;
END "READ IN A BLOCK FROM GRINNELL";
END "ELF INPUT";
END "GRNIN";
INTERNAL SIMPLE PROCEDURE EXE11BUF(INTEGER ADDR, BUFLEN);
Comment this procedure is for fast execution of grinnell commands that are
repeated often. It starts the DR11B using the ADDR and WORDCOUNT;
BEGIN "EXE11BUF"
IF NOT BUSTED THEN BEGIN
WHILE ¬(ELFIN(DRST) LAND READY) DO ;
ELFOUT(DRWC,-BUFLEN); Comment NOTE: word count not byte count;
ELFOUT(DRBA,(ADDR LAND '177777) LSH 1); comment MAKE INTO BYTE ADR;
ELFOUT(DRST,DRWRITE); comment Grinnell needs at least one clock;
comment cycle between setting of;
ELFOUT(DRST,GO LOR DRWRITE LOR ((ADDR LAND '300000) LSH -11));
comment write and go with extended bus addr bits;
END;
END "EXE11BUF";
INTERNAL SIMPLE PROCEDURE QUICKBUF;
Comment this procedure is for fast execution of grinnell commands that are
repeated often. It starts the DR11B using the ADDR and WORDCOUNT;
BEGIN "QUICKBUF"
OWN INTEGER BUFLEN;
BUFLEN ← NXTLOC - 1;
IF BUFLEN > 0 THEN
BEGIN
NXTLOC ← 1; comment restart word count;
IF NOT BUSTED THEN BEGIN
WHILE ¬(ELFIN(DRST) LAND READY) DO ;
ELFBKO(START11MEM,(BUFLEN),INSBUF,0); Comment move the buffer to the 11;
ELFOUT(DRWC,-BUFLEN); Comment NOTE: word count not byte count;
ELFOUT(DRBA,(START11MEM LAND '177777) LSH 1); comment MAKE INTO BYTE ADR;
ELFOUT(DRST,DRWRITE); comment Grinnell needs at least one clock;
comment cycle between setting of;
ELFOUT(DRST,GO LOR DRWRITE LOR ((START11MEM LAND '300000) LSH -11));
comment write and go with extended bus addr bits;
END;
END;
END "QUICKBUF";
INTERNAL SIMPLE PROCEDURE QUICKGIN(INTEGER ADDR, COUNT, READBACKMODE(0), USETBITS(0));
Comment this procedure is for fast input of data from the Grinnell to the
11. It starts the DR11B using the ADDR and WORDCOUNT
Since it does not wait (i.e. no snooze) it is suitable for space war
mode;
Comment An RPD instruction must be given prior to the call of this procedure;
BEGIN "QUICKGIN"
INTEGER CT;
IF NOT BUSTED THEN BEGIN
GRNINS(RPD LOR READBACKMODE);
! PRINT("waiting before loop 1 ", COUNT, crlf);
QUICKBUF;
for ct ← 1 step 1 until COUNT*5 do;
! CT ← COUNT*5;
! QUICK_CODE
! LABEL LOOP1;
! MOVE '13,CT;
! LOOP1: SOJG '13,LOOP1;
! END;
! PRINT("waiting at loop 1",crlf);
WHILE ¬(ELFIN(DRST) LAND READY) DO ; Comment Yes, this is the wait loop;
ELFOUT(DRWC,-COUNT); Comment NOTE: word count not byte count;
ELFOUT(DRBA,(START11MEM LAND '177777) LSH 1); comment MAKE INTO BYTE ADR;
ELFOUT(DRST,DRREAD); comment Grinnell needs at least one clock;
comment cycle between setting of;
ELFOUT(DRST,GO LOR DRREAD LOR ((START11MEM LAND '300000) LSH -11));
comment write and go with extended bus addr bits;
! CT ← COUNT*5;
! QUICK_CODE
! LABEL LOOP2;
! MOVE '13,CT;
! LOOP2: SOJG '13,LOOP2;
! END;
! PRINT("waiting before loop 2 ", COUNT, crlf);
for ct ← 1 step 1 until COUNT*5 do;
! PRINT("waiting at loop 2",crlf);
WHILE ¬(ELFIN(DRST) LAND READY) DO ; comment don't leave until done;
Comment check to see if words are packed when reading from the elf;
IF (USETBITS LAND TWOWRDSL) THEN COUNT ← COUNT/2 + (COUNT MOD 2);
ELFBKI(START11MEM,COUNT, ADDR,USETBITS); Comment input data from 11;
END
END "QUICKGIN";
INTERNAL PROCEDURE TSTGRN(INTEGER TESTNO);
Comment GRNTST runs the internal diagnostic test on the Grinnell. These are
designed to be run with TESTNO = 0, then 1, then 2 then 3, but this is
not mandatory.;
BEGIN "GRNTST"
GRNINS(SPD LOR TEST);
GRNINS(LPA LOR (TESTNO MOD 4));
BUFOUT;
END "GRNTST";
INTERNAL PROCEDURE MAPGRN(INTEGER CARD,TABL,NBITS);
Comment MAPGRN sets the video lookup table at CARD, TABL to show the least
significant NBITS bits.;
BEGIN "MAPGRN"
INTEGER ARRAY TMAP[0:255];
INTEGER I, BITMASK, LSHIFT;
BITMASK ← 2↑NBITS - 1; Comment mask with low NBITS on;
LSHIFT ← 8 - NBITS; Comment how far to shift the low NBITS;
FOR I ← 0 STEP 1 UNTIL 255 DO TMAP[I] ← (I LAND BITMASK) LSH LSHIFT;
IFVCMAP(CARD, TABL, TMAP);
BUFOUT;
END "MAPGRN";
INTERNAL PROCEDURE ERASEG(INTEGER CHAN,BITS('7777));
Comment Erase the indicated bits in the indicated channel;
BEGIN "ERASEG"
GRNINS(LDC LOR (1 LSH CHAN));
GRNINS(LSM LOR BITS);
GRNINS(LWM LOR 0); Comment dark background;
GRNINS(ERS);
BUFOUT;
END "ERASEG";
INTERNAL PROCEDURE VIDGRN(INTEGER LEFT, TOP, CHAN; INTEGER ARRAY PIC;
INTEGER SHIFTBY(0));
Comment VIDGRN outputs a gray-scale picture to the Grinnell.
LEFT - left margin of picture in pixels
TOP - top margin of picture in pixels
CHAN - channel of output;
BEGIN "VIDGRN"
INTEGER I;
INTEGER LINE,PIXEL; Comment Line number being output;
INTEGER UNPACK; Comment Address of unpacking "subroutine";
INTEGER ARRAY LINBUF[0:PIC[LNBY]]; Comment Buffer sent to 11;
GRNINS(LDC LOR (1 LSH CHAN)); Comment Select channel;
GRNINS(LSM LOR '377); Comment enable all subchannels;
GRNINS(LWM LOR BITZ); Comment Set write mode;
ifc TRACE thenc
print("Here we go on channel ",chan);
endc
GRNINS(LUM LOR E1); Comment Ea ← Ea+Eb mode;
GRNINS(LEB LOR 1); Comment Eb ← 1;
GRNINS(LLB LOR NEG1); Comment Lb ← -1;
GRNINS(LLA LOR TOP); Comment La ← top margin;
GRNINS(LEC LOR LEFT); Comment Ec ← left margin;
GRNINS(LEA LOR LEFT); Comment Set Ea to starting value;
Comment Flush anything that might be left over in the PDP11 buffer;
BUFOUT;
Comment Now that all control registers are set up, output all the lines of data.;
Comment I'm trying a new hack here, so for now I'm going to do things unpacked;
Comment assemble up instructions for unpacking one line into LINBUF;
Comment runtime assembler courtesy of PB;
BEGIN "RUNTIME ASSEMBLY"
REQUIRE "ASSEMB.SAI[S,HE]" SOURCE_FILE;
CBLK$_BEGIN(1);
L$(UNPACK);
FOR PIXEL ← 0 STEP 1 UNTIL PIC[LNBY]-1 DO
BEGIN "UNPACK AND STORE ONE PIXEL"
C$ ILDB(2,1);
IF SHIFTBY≠0 THEN C$ LSH(2,hr(SHIFTBY)); Comment HHB this crocko'shit doesnt work if
SHIFTBY<0 ... generates SHIFTBY !!!! changed to HR(Y) 25-5;
C$ MOVEM(2,LOC(LINBUF[0])+PIXEL);
END "UNPACK AND STORE ONE PIXEL";
C$ POPJ('17,0);
CBLK$_END(1);
END "RUNTIME ASSEMBLY";
Comment put SLU instruction at end of buffer;
LINBUF[PIC[LNBY]]←(SLU LOR L1 LOR E0); Comment Return to left margin and next line
(this is La ← La+Lb and Ea ← Ec);
IF PIC[LNBY]+1 > LEN11MEM THEN PRINT("Oh no!!!!!!! HELP!!!!!!!");
Comment Put the ELF in "risky but fast" mode (special system hack);
IF NOT ONVAX THEN RISKON;
Comment For each line;
FOR LINE ← 0 STEP 1 UNTIL PIC[PCLN]-1 DO
BEGIN
INTEGER BYTPTR;
Comment Set up byte pointer to the line in AC1, then unpack the
line into LINBUF;
BYTPTR←MEMORY[PIC[BPTAB]-1]+PIC[LINTAB+LINE];
START_CODE
MOVE 1,BYTPTR;
PUSHJ '17,@UNPACK;
END;
Comment Transfer the instructions to the PDP-11...;
IF ONVAX THEN ENETOUT(LINBUF,PIC[LNBY]+1)
ELSE GRNBUF(LINBUF,PIC[LNBY]+1,0);
IF DEMO THEN
FOR I ← 0 STEP 1 UNTIL PIC[LNBY] DO DEMOWORD(LINBUF[I]);
END;
Comment Take the ELF out of its funny mode;
IF NOT ONVAX THEN RISKOFF;
END "VIDGRN";
PROCEDURE PACKBYTES(INTEGER BYTE1PTR, BYTE2PTR,DESTPTR, NBYTES);
BEGIN "PACKBYTES"
LABEL LOOP;
START_CODE
MOVE 3,BYTE1PTR;
MOVE 4,BYTE2PTR;
MOVE 5,DESTPTR;
MOVE 1,NBYTES;
ash 1,-1;
LOOP: LDB 2,3;
IDPB 2,5;
AOS 3;
LDB 2,4;
IDPB 2,5;
AOS 4;
SOJG 1,LOOP;
END;
END "PACKBYTES";
PROCEDURE HACKBYTES(INTEGER ADDR, DESTPTR, NWORDS);
BEGIN "HACKBYTES"
LABEL LOOP;
START_CODE
MOVE 3,ADDR;
MOVE 5,DESTPTR;
MOVE 1,NWORDS;
LOOP: MOVE 2,0(3);
IDPB 2,5;
AOS 3;
SOJG 1,LOOP;
END;
END "HACKBYTES";
INTERNAL PROCEDURE InLine(REFERENCE INTEGER Ptr; INTEGER linelen);
BEGIN "InLine"
INTEGER element;
INTEGER ARRAY LineIn[1:Linelen/2];
! Now get one scan line from the Grinnell and store it in the 11`s buffer;
! and input line from the 11`s memory through the ELF;
! The data is read in in packed mode from the Grinnell and then two words per;
! word left justified from the 11;
GRNIN(LOCATION(LINEIN[1]), Linelen/2, BYTEPACK,TWOWRDSL);
FOR element ← 0 STEP 1 UNTIL linelen/4 -1 DO
MEMORY[ptr + element] ← lineIn[element +1];
END "InLine";
INTERNAL PROCEDURE INPIC(INTEGER CHAN; INTEGER ARRAY PIC);
BEGIN "InPic"
INTEGER line, ptr;
DEFINE HEIGHT = 512,
WIDTH = 512,
BITS = 8;
! Make blank picture with dimensions HxWxB;
MAKPIX(HEIGHT,WIDTH,BITS,PIC[0]);
GRNINI; ! Set up Grinnell buffers;
GRNINS(LDC LOR (1 LSH CHAN)); ! Select channel;
GRNINS(SPD LOR READBACK); ! Set read mode;
GRNINS(LUM LOR E1); ! Ea ← Ea+Eb mode;
GRNINS(LEB LOR 1); ! Eb ← 1;
GRNINS(LLB LOR NEG1); ! Lb ← -1;
GRNINS(LLA LOR HEIGHT-1); ! La ← top margin;
GRNINS(LEC LOR 0); ! Ec ← left margin;
GRNINS(LEA LOR 0); ! Set Ea to starting value;
! Send these commands off to the Grinnell;
BUFOUT;
! Input first line of picture form Grinnell;
PTR ← MEMORY[PIC[BPTAB]-1,INTEGER] + PIC[LINTAB]; Comment get byte ptr;
InLine(Ptr, width);
! Now get the rest;
FOR line ← 2 step 1 until Height DO
BEGIN
GRNINS(SLU LOR L1 LOR E0);
BUFOUT;
PTR ← MEMORY[PIC[BPTAB]-1,INTEGER]+PIC[LINTAB+LINE-1]; Comment get byte ptr;
IfC trace THENC
print(line," ");
ENDC
InLine(Ptr, width);
END;
! Finished so relaese ELF;
GRNFIN;
END "InPic";
INTERNAL PROCEDURE UINPIC(INTEGER CHAN; INTEGER ARRAY PIC);
BEGIN "UInPic"
DEFINE HEIGHT = 512,
WIDTH = 512,
BITS = 8;
INTEGER line, ptr;
INTEGER ARRAY LINEIN[1:WIDTH]; ! really only need WIDTH/2 for ELF;
! Make blank picture with dimensions HxWxB;
MAKPIX(HEIGHT,WIDTH,BITS,PIC[0]);
GRNINI; ! Set up Grinnell buffers;
GRNINS(LDC LOR (1 LSH CHAN)); ! Select channel;
GRNINS(LSM LOR '377); ! Enable read back of all 8 bits;
GRNINS(LEA LOR 0); ! Set Ea to starting value;
GRNINS(LEB LOR 1); ! Eb ← 1;
GRNINS(LLA LOR HEIGHT-1); ! La ← top margin;
GRNINS(LLB LOR '777); ! Lb ← -1;
GRNINS(LEC LOR 0); ! Ec ← left margin;
GRNINS(LUM LOR E1); ! Ea ← Ea+Eb mode;
GRNINS(SPD LOR READBACK); ! Set read mode;
! Send these commands off to the Grinnell;
BUFOUT;
! Input first line of picture form Grinnell;
PTR ← MEMORY[PIC[BPTAB]-1,INTEGER] + PIC[LINTAB]; Comment get byte ptr;
GRNIN(LOCATION(LINEIN[1]), WIDTH,0,TWOWRDSL);
IF ONVAX THEN
HACKBYTES(LOCATION(LINEIN[1]),PTR,WIDTH)
ELSE
PACKBYTES(POINT(BITS,LINEIN[1],15),POINT(BITS,LINEIN[1],31),PTR,WIDTH);
! Now get the rest;
FOR line ← 2 step 1 until Height DO
BEGIN
GRNINS(SLU LOR L1 LOR E0);
! try this;
! GRNINS(LLA LOR (HEIGHT-line));
! GRNINS(LEA LOR 0);
PTR ← MEMORY[PIC[BPTAB]-1,INTEGER]+PIC[LINTAB+LINE-1]; Comment get byte ptr;
IFC TRACE THENC
print(line," ");
ENDC
GRNIN(LOCATION(LINEIN[1]), WIDTH,0,TWOWRDSL);
IF ONVAX THEN
HACKBYTES(LOCATION(LINEIN[1]),PTR,WIDTH)
ELSE
PACKBYTES(POINT(BITS,LINEIN[1],15),POINT(BITS,LINEIN[1],31),PTR,WIDTH);
comment shit, changed to 31 after several days of crappy input;
END;
! Finished so release ELF;
GRNFIN;
END "UInPic";
END "GRNSAI";